// osobject.h : 
// 

#ifndef _WINOBJECT_H_KOG_
#define _WINOBJECT_H_KOG_

#include "basictypes.h"
#include <memory>

NAMESPACE_BEGIN(kog);

template<typename _Return> struct zero_function
{
	typedef _Return result_type;
};

template<typename _Fn1> struct unary2zero_t : public zero_function<typename _Fn1::result_type>
{
public:
	typedef zero_function<typename _Fn1::result_type> _Base;
	typedef typename _Base::result_type result_type;
	typedef typename _Fn1::argument_type argument_type;

	unary2zero_t(const _Fn1& _Func, const typename argument_type& var)
		: _op(_Func), _value(var)
	{}

	typename result_type operator()() const
	{
		return _op(_value);
	}

protected:
	_Fn1 _op;
	typename argument_type _value;	// the left operand
};

template<typename _Fn1> struct unary2zero_ref_t : public zero_function<typename _Fn1::result_type>
{
public:
	typedef zero_function<typename _Fn1::result_type> _Base;
	typedef typename _Base::result_type result_type;
	typedef typename _Fn1::argument_type argument_type;

	unary2zero_ref_t(const _Fn1& _Func, typename argument_type& var)
		: _op(_Func), _value(var)
	{}

	typename result_type operator()() const
	{
		return _op(_value);
	}

protected:
	_Fn1 _op;
	typename argument_type& _value;	// the left operand
};

template<typename _Fn, typename _Ty> unary2zero_ref_t<_Fn> unary2zero_ref(const _Fn& fn, _Ty& v)
{
	unary2zero_ref_t<_Fn> tmp(fn, v);
	return tmp;
}

template<typename _Fn, typename _Ty> unary2zero_t<_Fn> unary2zero(const _Fn& fn, const _Ty& v)
{
	unary2zero_t<_Fn> tmp(fn, v);
	return tmp;
}


NAMESPACE_BEGIN(os);

class ithread
{
public:
	static void entry_function(void* p)
	{
		ithread* pt = (ithread*)p;
		if (pt != NULL) 
		{
			(*pt)();
			delete pt;
		}
	}
private:
	virtual void operator()() = 0;
};

template<typename _Fun_type> class thread : public ithread
{
public:
	thread(_Fun_type fun)
		: _fun(fun) {}
private:
	/* overwrite */ void operator()()
	{
		_fun();
	}
private:
	_Fun_type _fun;
};

class osobject
{
public:
	typedef void* winhandle;
public:
	enum handle_type
	{
		pipe, semaphore, xevent, /*critical_section,*/ mutex, thread, none
	};
public:
	osobject(void);
	osobject(winhandle handle);
	virtual ~osobject(void);
public:
	// sleep ms
	static void sleep(int ms);
public:
	// create a semaphore object
	osobject& create_semaphore(long initCount = 1, long maxCount = 1/*, const std::string& name = "", void* pAttributes = NULL*/);

	// create an event object
	osobject& create_event(bool initOwn = false, bool manualReset = false/*, const std::string& name = "", void* pAttributes = NULL*/);

	osobject& create_mutex(bool initOwn = false/*, const std::string& name = "", void* pAttributes = NULL*/);

	// create thread
	template<typename _Fun> osobject& create_thread(_Fun fun)
	{
		std::auto_ptr<kog::os::thread<_Fun> > pFun(new kog::os::thread<_Fun>(fun));
		_create_thread(pFun.get());
		pFun.release();
		return *this;
	}
private:
	void _create_thread(ithread* p);
public:
	bool is_valid() const;
public:
	// wait
	int wait(int timeout = -1);

	// release
	bool release();

	// close handle
	void close();
public:
	// get handle
	winhandle get() const;
	// get type
	handle_type htype() const;
public:
	osobject& reset(winhandle handle);
public:
	winhandle _handle;
	handle_type _type;
};

NAMESPACE_END(os);
NAMESPACE_END(kog);

#endif
